﻿using SyncCore.Sync.Models;
using System.Net;

namespace SyncCore.Sync.FrameSync
{
    internal class FrameMessageCache
    {
        public int FrameIndex { get; set; }

        public bool IsAllCollected => GetIsAllCollected();

        public bool IsAllReady => GetIsAllReady();

        public Dictionary<EndPoint, ClientFrameMessage> Messages { get; set; }
        private ClientFrameMessage[] _clientFrameMessages;
        private HashSet<EndPoint> _endPoints = new HashSet<EndPoint>();
        public FrameMessageCache(IEnumerable<EndPoint> endPoints)
        {
            _clientFrameMessages = endPoints.Select(i => new ClientFrameMessage() { EndPoint = i }).ToArray();
            Messages = _clientFrameMessages.ToDictionary(i => i.EndPoint);

            FrameIndex = 0;
        }

        public bool Collect(EndPoint endPoint, MessagePack messagePack)
        {
            if (endPoint == null) return false;
            if (messagePack == null) return false;
            if (messagePack.FrameIndex < 0) return false;
            if (Messages.ContainsKey(endPoint) == false) return false;
            if (messagePack.Type != MessageType.RPC) return false;
            if (messagePack.FrameIndex != FrameIndex) return false;

            var message = Messages[endPoint];
            message.AddRange(messagePack.Commands);

            return true;
        }

        public void CollectReady(EndPoint endPoint)
        {
            _endPoints.Add(endPoint);
        }

        private bool GetIsAllReady()
        {
            return _clientFrameMessages.Length == _endPoints.Count;
        }

        private bool GetIsAllCollected()
        {
            foreach (var clientFrameMessage in _clientFrameMessages)
            {
                if (clientFrameMessage.IsChanged == false) return false;
            }

            return true;
        }

        public void SetNextFrameIndex()
        {
            Console.WriteLine($"FrameMessageCache.SetNextFrameIndex: {FrameIndex} -> {FrameIndex+1} ");
            FrameIndex = FrameIndex + 1;
            foreach (var clientFrameMessage in _clientFrameMessages)
            {
                clientFrameMessage.Reset();
            }
        }

        ///<summary>创建当前帧的汇总命令</summary>
        public MessagePack CreateAssembledMessagePack()
        {
            var messagePack = new MessagePack();
            messagePack.Type = MessageType.RPC;
            var list = new List<CommandMessagePack>();
            messagePack.FrameIndex = FrameIndex;

            foreach (var clientFrameMessage in _clientFrameMessages)
            {
                foreach (var command in clientFrameMessage.Commands)
                {
                    list.Add(command);
                }
            }

            messagePack.Commands = list.ToArray();

            return messagePack;
        }


    }
}
